﻿
namespace Math2DStruct
{
    //线段的定义
    public struct LineSegment
    {
        public XVector2 pos1;
        public XVector2 pos2;

        public LineSegment(XVector2 p1, XVector2 p2)
        {
            pos1 = p1;
            pos2 = p2;
        }

        public XNumber Distance(XVector2 pos)
        {
            var verticalDistance = XNumber.MaxValue;
            var distanceOne = XNumber.MaxValue;
            var distanceTwo = XNumber.MaxValue;

            var lineDir = pos1 - pos2;
            var verticalDir = lineDir.RotateSelf(90);
            var crossPoint = Math2D.Point_Cross_LineAndLine(pos1, lineDir, pos, verticalDir);
            if (crossPoint != null)
                verticalDistance = XVector2.Distance(pos, crossPoint.Value);

            distanceOne = XVector2.Distance(pos, pos1);
            distanceTwo = XVector2.Distance(pos, pos2);

            return XIntMath.Min(verticalDistance, XIntMath.Min(distanceOne, distanceTwo));
        }

        /// <summary>
        /// 注意position假设已经在该线段的直线上;
        /// </summary>
        /// <param name="position"></param>
        /// <returns></returns>
        public bool CheckIn(XVector2 position)
        {
            if (position == pos1 || position == pos2)
            {
                return true;
            }
            else
            {
                var dir1 = pos1 - position;
                var dir2 = pos2 - position;

                var angle = XVector2.AngleAbs(dir1, dir2);
                return angle > 170; //近似算法, 大概在线上就行了, 浮点精度所致
            }
        }

        public XVector2? IntersectionPoint(Line line)
        {
            var self = new Line(pos1, pos2 - pos1);
            var ret = Math2D.Point_Cross_LineAndLine(line, self);
            if (ret.HasValue && CheckIn(ret.Value))
                return ret;
            else
                return null;
        }

        public XVector2? IntersectionPoint(LineSegment line)
        {
            var self = new Line(pos1, pos2 - pos1);
            var tar = new Line(line.pos1, line.pos2 - line.pos1);
            var ret = Math2D.Point_Cross_LineAndLine(tar, self);
            if (ret.HasValue && CheckIn(ret.Value) && line.CheckIn(ret.Value))
                return ret;
            else
                return null;
        }
    }
}
